package cn.iocoder.yudao.module.digital.service.cardkeysecret;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.digest.MD5;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.digital.controller.admin.cardkeyproduct.vo.CardKeyProductImportExcelVO;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.CardKeySourceEnum;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.ClaimStatusEnum;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import cn.iocoder.yudao.module.digital.controller.admin.cardkeysecret.vo.*;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeysecret.CardkeySecretDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.digital.dal.mysql.cardkeysecret.CardkeySecretMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.digital.enums.ErrorCodeConstants.*;

/**
 * 卡密密钥 Service 实现类
 *
 * @author 超管
 */
@Service
@Validated
public class CardkeySecretServiceImpl implements CardkeySecretService {

    @Resource
    private CardkeySecretMapper cardkeySecretMapper;

    @Override
    public String createCardkeySecret(CardkeySecretSaveReqVO createReqVO) {
        final String id = genId(createReqVO.getSource(), createReqVO.getProductNo(), createReqVO.getEGiftId());
        createReqVO.setId(id);

        // 插入
        CardkeySecretDO cardSecret = BeanUtils.toBean(createReqVO, CardkeySecretDO.class);
        cardkeySecretMapper.insert(cardSecret);

        // 返回
        return cardSecret.getId();
    }

    private static String genId(Integer source, String productNo, String eGiftId) {
        if (StrUtil.isEmpty(eGiftId)) {
            throw new NullPointerException("eGiftId不能为空");
        }

        final String id = new Digester(DigestAlgorithm.MD5).digestHex(source + productNo + eGiftId);
        return id;
    }

    @Override
    public void updateCardkeySecret(CardkeySecretSaveReqVO updateReqVO) {
        // 校验存在
        validateCardkeySecretExists(updateReqVO.getId());
        // 更新
        CardkeySecretDO updateObj = BeanUtils.toBean(updateReqVO, CardkeySecretDO.class);
        cardkeySecretMapper.updateById(updateObj);
    }

    private void validateCardkeySecretExists(String id) {
        if (cardkeySecretMapper.selectById(id) == null) {
            throw exception(CARDKEY_SECRET_NOT_EXISTS);
        }
    }

    @Override
    public CardkeySecretDO getCardkeySecret(String id) {
        return cardkeySecretMapper.selectById(id);
    }

    @Override
    public PageResult<CardkeySecretDO> getCardkeySecretPage(CardkeySecretPageReqVO pageReqVO) {
        return cardkeySecretMapper.selectPage(pageReqVO);
    }

    /**
     * 查询卡密
     *
     * @param claimStatusEnum 领取状态
     * @param productNo       卡密商品编号
     * @param limitSize       查询的数量
     * @return
     */
    @Override
    public List<CardkeySecretDO> getCardKeySecretByProductNoAndClaimStatus(ClaimStatusEnum claimStatusEnum, String productNo, Integer denomination,
                                                                           int limitSize) {
        return cardkeySecretMapper.getCardKeySecretByProductNo(claimStatusEnum, productNo, denomination, limitSize);
    }

    @Override
    public long countCardKeySecretByProductNo(ClaimStatusEnum claimStatusEnum, String productNo, Integer denomination) {
        return cardkeySecretMapper.countCardKeySecretByProductNo(claimStatusEnum, productNo, denomination);
    }

    /**
     * 扣减密钥
     *
     * @param userId
     * @param orderNo
     * @param secretIds
     */
    @Override
    public void deductionSecret(Long userId, String orderNo, Collection<String> secretIds) {
        cardkeySecretMapper.deductionSecret(userId, orderNo, secretIds);
    }

    /**
     * 写卡密密钥数据
     *
     * @param list
     */
    @Override
    public void batchCreateCardKeySecret(CardKeySourceEnum source, List<CardKeyProductImportExcelVO> list) {
        final List<CardkeySecretDO> doList = new ArrayList<>();
        for (CardKeyProductImportExcelVO vo : list) {
            final CardkeySecretDO secret = new CardkeySecretDO();
            secret.setEGiftId(IdUtil.objectId());
            secret.setSource(source.getValue());
            secret.setProductNo(vo.getProductNo());
            secret.setClaimStatus(ClaimStatusEnum.NO.getValue());
            final int denominationFixed = vo.getDenominationFixed().multiply(new BigDecimal(100)).intValue();// 元转换为分
            secret.setDenomination(denominationFixed);
            secret.setCurrencyCode(vo.getCurrencyCode());
            final int costPrice = vo.getCostPrice().multiply(new BigDecimal(100)).intValue();// 元转换为分
            secret.setCostPrice(costPrice);
            secret.setCardNumber(vo.getCardNumber());
            secret.setCode(vo.getCode());
            secret.setPin(vo.getPin());

            final String id = genId(secret.getSource(), secret.getProductNo(), secret.getEGiftId());
            secret.setId(id);
            doList.add(secret);
        }
        cardkeySecretMapper.insertBatch(doList);
    }

    /**
     * 查询已经领取的卡密
     *
     * @param orderNo
     * @return
     */
    @Override
    public List<CardkeySecretDO> getCardKeySecretByOrderNo(String orderNo) {
        return cardkeySecretMapper.getCardKeySecretByOrderNo(orderNo);
    }

    @Override
    public List<CardkeySecretDO> getCardKeySecretByOrderNo(Long userId, String orderNo) {
        return cardkeySecretMapper.getCardKeySecretByOrderNo(userId, orderNo);
    }

    @Override
    public CardkeySecretDO getCardKeySecretByNumberCodePin(ClaimStatusEnum claimStatusEnum, String cardNumber, String code, String pin) {
        return cardkeySecretMapper.getCardKeySecretByNumberCodePin(claimStatusEnum, cardNumber, code, pin);
    }

    @Override
    public Long getStock(String productNo) {
        return cardkeySecretMapper.getStock(productNo);
    }

    @Override
    public List<CardkeySecretDO> getByCardKeySecret(String cardKeySecret) {
        return cardkeySecretMapper.selectList(new LambdaQueryWrapperX<CardkeySecretDO>()
                .eq(CardkeySecretDO::getCode, cardKeySecret).or().eq(CardkeySecretDO::getCardNumber, cardKeySecret));
    }

}